home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / socket.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  47KB  |  2,072 lines

  1. /* Application programming interface routines - based loosely on the
  2.  * "socket" model in Berkeley UNIX.
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  */
  6. #include <stdio.h>
  7. #include <time.h>
  8. #ifdef  __STDC__
  9. #include <stdarg.h>
  10. #endif
  11. #include "global.h"
  12. #include "config.h"
  13. #include "mbuf.h"
  14. #include "netuser.h"
  15. #include "timer.h"
  16. #include "iface.h"
  17. #include "ip.h"
  18. #include "tcp.h"
  19. #include "udp.h"
  20. #include "ax25.h"
  21. #include "lapb.h"
  22. #include "netrom.h"
  23. #include "nr4.h"
  24. #include "proc.h"
  25. #include "lzw.h"
  26. #include "usock.h"
  27. #include "socket.h"
  28.  
  29. /* In connect(), accept() and recv_mbuf()
  30.  * the noblock options have been removed, since they never occur anyway.
  31.  * If you want then back, do a '#define useblock 1'
  32.  * The socket's 'noblock' parameter is now only effective for sending
  33.  * data; ie if set, only sending data will not block. - WG7J
  34.  */
  35.  
  36.  
  37. static void autobind __ARGS((int s,int af));
  38. static int checkaddr __ARGS((int type,char *name,int namelen));
  39. static void rip_recv __ARGS((struct raw_ip *rp));
  40. static void s_trcall __ARGS((struct tcb *tcb,int cnt));
  41. static void s_tscall __ARGS((struct tcb *tcb,int old,int new));
  42. static void s_ttcall __ARGS((struct tcb *tcb,int cnt));
  43. static void s_urcall __ARGS((struct iface *iface,struct udp_cb *udp,int cnt));
  44. static void trdiscard __ARGS((struct tcb *tcb,int cnt));
  45. #ifdef    NETROM
  46. static void s_nrcall __ARGS((struct nr4cb *cb,int16 cnt));
  47. static void s_nscall __ARGS((struct nr4cb *cb,int old,int new));
  48. static void s_ntcall __ARGS((struct nr4cb *cb,int16 cnt));
  49. #endif
  50.  
  51. static int16 Lport = 1024;
  52.  
  53. char *Socktypes[] = {
  54.     "Not Used",
  55.     "TCP",
  56.     "UDP",
  57.     "AX25 I",
  58.     "AX25 UI",
  59.     "Raw IP",
  60.     "NETROM3",
  61.     "NETROM",
  62.     "Loc St",
  63.     "Loc Dg"
  64. };
  65. char Badsocket[] = "Bad socket";
  66. struct usock *Usock;        /* Socket entry array */
  67. int Nusock = DEFNSOCK;        /* Number of socket entries */
  68.  
  69. /* The following two variables are needed because there can be only one
  70.  * socket listening on each of the AX.25 modes (I and UI)
  71.  */
  72. #ifdef    AX25
  73. int Axi_sock = -1;    /* Socket number listening for AX25 connections */
  74.  
  75. #ifdef notdef
  76. static int Axui_sock = -1;  /* Socket number listening for AX25 UI frames */
  77. static struct mbuf *Bcq;    /* Queue of incoming UI frames */
  78.  
  79. /* Function that handles incoming UI frames from lapb.c */
  80. void
  81. beac_input(iface,src,bp)
  82. struct iface *iface;
  83. char *src;
  84. struct mbuf *bp;
  85. {
  86.     struct mbuf *hdr;
  87.     struct sockaddr_ax *sax;
  88.  
  89.     if(Axui_sock == -1){
  90.         /* Nobody there to read it */
  91.         free_p(bp);
  92.     } else {
  93.         if((hdr = pushdown(NULLBUF,sizeof(struct sockaddr_ax))) == NULLBUF){
  94.             free_p(bp);
  95.             return;
  96.         }
  97.         sax = (struct sockaddr_ax *)hdr->data;
  98.         sax->sax_family = AF_AX25;
  99.         memcpy(sax->ax25_addr,src,AXALEN);
  100.         strncpy(sax->iface,iface->name,ILEN);
  101.         hdr->next = bp;
  102.         enqueue(&Bcq,hdr);
  103.     }
  104. }
  105. #endif
  106. #endif /* AX.25 */
  107.  
  108. /* Initialize user socket array */
  109. void
  110. sockinit()
  111. {
  112.     if(Usock != NULLUSOCK)
  113.         return;    /* Already initialized */
  114.     Usock = (struct usock *)callocw((unsigned)Nusock,sizeof(struct usock));
  115. }
  116.  
  117. /* Create a user socket, return socket index
  118.  * The mapping to actual protocols is as follows:
  119.  *        
  120.  *        
  121.  * ADDRESS FAMILY    Stream        Datagram    Raw        Seq. Packet
  122.  *
  123.  * AF_INET        TCP        UDP        IP
  124.  * AF_AX25        I-frames    UI-frames
  125.  * AF_NETROM                        NET/ROM L3  NET/ROM L4
  126.  * AF_LOCAL        stream loopback    packet loopback
  127.  */
  128. int
  129. socket(af,type,protocol)
  130. int af;        /* Address family */
  131. int type;    /* Stream or datagram */
  132. int protocol;    /* Used for raw IP sockets */
  133. {
  134.     register struct usock *up;
  135.     int s;
  136.  
  137.     for(up=Usock;up < &Usock[Nusock];up++)
  138.         if(up->type == NOTUSED)
  139.             break;
  140.  
  141.     if(up == &Usock[Nusock]){
  142.         /* None left */
  143.         errno = EMFILE;
  144.         return -1;
  145.     }
  146.     /* set the time the socket was created - WG7J */
  147.     up->created = time(NULL);
  148.     up->refcnt = 1;
  149.     s = up - Usock + SOCKBASE;
  150.     errno = 0;
  151.     up->noblock = 0;
  152.     up->rdysock = -1;
  153.     up->cb.p = NULLCHAR;
  154.     up->peername = up->name = NULLCHAR;
  155.     up->namelen = up->peernamelen = 0;
  156.     up->owner = Curproc;
  157.     up->obuf = NULLBUF;
  158.     memset(up->errcodes,0,sizeof(up->errcodes));
  159.     memset(up->eol,0,sizeof(up->eol));
  160.     up->flush = '\n';    /* default is line buffered */
  161.     switch(af){
  162.     case AF_LOCAL:
  163.         up->cb.local = (struct loc *) callocw(1,sizeof(struct loc));
  164.         up->cb.local->peer = up;    /* connect to self */
  165.         switch(type){
  166.         case SOCK_STREAM:
  167.             up->type = TYPE_LOCAL_STREAM;
  168.             up->cb.local->hiwat = LOCSFLOW;
  169.             break;
  170.         case SOCK_DGRAM:
  171.             up->type = TYPE_LOCAL_DGRAM;
  172.             up->cb.local->hiwat = LOCDFLOW;
  173.             break;
  174.         default:
  175.             free(up->cb.local);
  176.             errno = ESOCKTNOSUPPORT;
  177.             break;
  178.         }
  179.         break;
  180. #ifdef    AX25
  181.     case AF_AX25:
  182.         switch(type){
  183.         case SOCK_STREAM:
  184.             up->type = TYPE_AX25I;
  185.             break;
  186.         case SOCK_DGRAM:
  187.             up->type = TYPE_AX25UI;
  188.             break;
  189.         default:
  190.             errno = ESOCKTNOSUPPORT;
  191.             break;
  192.         }
  193.         strcpy(up->eol,AX_EOL);
  194.         break;
  195. #endif
  196. #ifdef NETROM
  197.     case AF_NETROM:
  198.         switch(type){
  199.         case SOCK_RAW:
  200.             up->type = TYPE_NETROML3;
  201.             up->cb.rnr = raw_nr((char)protocol);
  202.             break;
  203.         case SOCK_SEQPACKET:
  204.             up->type = TYPE_NETROML4;
  205.             break;
  206.         default:
  207.             errno = ESOCKTNOSUPPORT;
  208.             break;
  209.         }
  210.         strcpy(up->eol,AX_EOL);
  211.         break;
  212. #endif
  213.     case AF_INET:
  214.         switch(type){
  215.         case SOCK_STREAM:
  216.             up->type = TYPE_TCP;
  217.             strcpy(up->eol,INET_EOL);
  218.             break;
  219.         case SOCK_DGRAM:
  220.             up->type = TYPE_UDP;
  221.             break;
  222.         case SOCK_RAW:
  223.             up->type = TYPE_RAW;
  224.             up->cb.rip = raw_ip(protocol,rip_recv);
  225.                         up->cb.rip->user = s;
  226.             break;
  227.         default:
  228.             errno = ESOCKTNOSUPPORT;
  229.             break;
  230.         }
  231.         break;
  232.     default:
  233.         errno = EAFNOSUPPORT;
  234.         break;
  235.     }
  236.     if(errno)
  237.         return -1;
  238.  
  239.     return s;
  240. }
  241.  
  242. /* Attach a local address/port to a socket. If not issued before a connect
  243.  * or listen, will be issued automatically
  244.  */
  245. int
  246. bind(s,name,namelen)
  247. int s;        /* Socket index */
  248. char *name;    /* Local name */
  249. int namelen;    /* Length of name */
  250. {
  251.     register struct usock *up;
  252.     union sp local;
  253.     struct socket lsock;
  254.  
  255.     if((up = itop(s)) == NULLUSOCK){
  256.         errno = EBADF;
  257.         return -1;
  258.     }
  259.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  260.         errno = EINVAL;
  261.         return -1;
  262.     }
  263.     if(name == NULLCHAR){
  264.         errno = EFAULT;
  265.         return -1;
  266.     }
  267.     if(up->name != NULLCHAR){
  268.         /* Bind has already been issued */
  269.         errno = EINVAL;
  270.         return -1;
  271.     }
  272.     if(checkaddr(up->type,name,namelen) == -1){
  273.         /* Incorrect length or family for chosen protocol */
  274.         errno = EAFNOSUPPORT;
  275.         return -1;    
  276.     }
  277.     /* Stash name in an allocated block */
  278.     up->namelen = namelen;
  279.     up->name = mallocw((unsigned)namelen);
  280.     memcpy(up->name,name,(size_t)namelen);
  281.     /* Create control block for datagram sockets */
  282.     switch(up->type){
  283.     case TYPE_UDP:
  284.         local.in = (struct sockaddr_in *)up->name;
  285.         lsock.address = local.in->sin_addr.s_addr;
  286.         lsock.port = local.in->sin_port;
  287.         up->cb.udp = open_udp(&lsock,s_urcall);
  288.         up->cb.udp->user = s;
  289.         break;
  290. #ifdef  notdef
  291.     case TYPE_AX25UI:
  292.         if(Axui_sock != -1){
  293.             errno = EADDRINUSE;
  294.             return -1;
  295.         }
  296.         Axui_sock = s;
  297.         break;
  298. #endif
  299.     }
  300.     return 0;
  301. }
  302. /* Post a listen on a socket */
  303. int
  304. listen(s,backlog)
  305. int s;        /* Socket index */
  306. int backlog;    /* 0 for a single connection, 1 for multiple connections */
  307. {
  308.     register struct usock *up;
  309.     union sp local;
  310.     struct socket lsock;
  311.  
  312.     if((up = itop(s)) == NULLUSOCK){
  313.         errno = EBADF;
  314.         return -1;
  315.     }
  316.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  317.         errno = EINVAL;
  318.         return -1;
  319.     }
  320.     if(up->cb.p != NULLCHAR){
  321.         errno = EISCONN;
  322.         return -1;
  323.     }
  324.     switch(up->type){
  325.     case TYPE_TCP:
  326.         if(up->name == NULLCHAR)
  327.             autobind(s,AF_INET);
  328.  
  329.         local.in = (struct sockaddr_in *)up->name;
  330.         lsock.address = local.in->sin_addr.s_addr;
  331.         lsock.port = local.in->sin_port;
  332.         up->cb.tcb = open_tcp(&lsock,NULLSOCK,
  333.          backlog ? TCP_SERVER:TCP_PASSIVE,0,
  334.         s_trcall,s_ttcall,s_tscall,0,s);
  335.         break;
  336. #ifdef AX25
  337.     case TYPE_AX25I:
  338.         if(up->name == NULLCHAR)
  339.             autobind(s,AF_AX25);
  340.         if(s != Axi_sock){
  341.             errno = EOPNOTSUPP;
  342.             return -1;
  343.         }
  344.         local.ax = (struct sockaddr_ax *)up->name;
  345.         up->cb.ax25 = open_ax25(NULLIF,local.ax->ax25_addr,NULLCHAR,
  346.          backlog ? AX_SERVER:AX_PASSIVE,0,
  347.          s_arcall,s_atcall,s_ascall,s);
  348.         break;
  349. #endif
  350. #ifdef NETROM
  351.     case TYPE_NETROML4:
  352.         if(up->name == NULLCHAR)
  353.             autobind(s,AF_NETROM);
  354.         local.nr = (struct sockaddr_nr *)up->name;
  355.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,NULLNRADDR,
  356.          backlog ? AX_SERVER:AX_PASSIVE,
  357.          s_nrcall,s_ntcall,s_nscall,s);
  358.         break;
  359. #endif
  360.     default:
  361.         /* Listen not supported on datagram sockets */
  362.         errno = EOPNOTSUPP;
  363.         return -1;        
  364.     }
  365.     return 0;
  366. }
  367.  
  368. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  369. int
  370. connect(s,peername,peernamelen)
  371. int s;            /* Socket index */
  372. char *peername;        /* Peer name */
  373. int peernamelen;    /* Length of peer name */
  374. {
  375.     register struct usock *up;
  376.     union cb cb;
  377.     union sp local,remote;
  378.     struct socket lsock,fsock;
  379. #ifdef    AX25
  380.     struct iface *iface;
  381. #endif
  382.  
  383. #ifndef UNIX
  384.     if(availmem() < Memthresh){  /* Not enough resources - WG7J */
  385.         errno = ENOMEM;
  386.         return -1;
  387.     }
  388. #endif
  389.     if((up = itop(s)) == NULLUSOCK){
  390.         errno = EBADF;
  391.         return -1;
  392.     }
  393.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  394.         errno = EINVAL;
  395.         return -1;
  396.     }
  397.     if(peername == NULLCHAR){
  398.         /* Connect must specify a remote address */
  399.         errno = EFAULT;
  400.         return -1;
  401.     }
  402.     if(checkaddr(up->type,peername,peernamelen) == -1){
  403.         errno = EAFNOSUPPORT;
  404.         return -1;
  405.     }
  406.     /* Raw socket control blocks are created in socket() */
  407.     if(up->type != TYPE_RAW && up->type != TYPE_NETROML3 &&
  408.        up->cb.p != NULLCHAR){
  409.         errno = EISCONN;
  410.         return -1;
  411.     }
  412.     up->peername = mallocw((unsigned)peernamelen);
  413.     memcpy(up->peername,peername,(size_t)peernamelen);
  414.     up->peernamelen = peernamelen;
  415.  
  416.     /* Set up the local socket structures */
  417.     if(up->name == NULLCHAR){
  418.         switch(up->type){
  419.         case TYPE_TCP:
  420.         case TYPE_UDP:
  421.         case TYPE_RAW:
  422.             autobind(s,AF_INET);
  423.             break;
  424. #ifdef    AX25
  425.         case TYPE_AX25I:
  426.         case TYPE_AX25UI:
  427.             autobind(s,AF_AX25);
  428.             break;
  429. #endif
  430. #ifdef    NETROM
  431.         case TYPE_NETROML3:
  432.         case TYPE_NETROML4:
  433.             autobind(s,AF_NETROM);
  434.             break;
  435. #endif
  436.         }
  437.     }
  438.     switch(up->type){
  439.     case TYPE_TCP:
  440.         /* Construct the TCP-style ports from the sockaddr structs */
  441.         local.in = (struct sockaddr_in *)up->name;
  442.         remote.in = (struct sockaddr_in *)up->peername;
  443.  
  444.         if(local.in->sin_addr.s_addr == INADDR_ANY)
  445.             /* Choose a local address */
  446.             local.in->sin_addr.s_addr =
  447.              locaddr((int32)remote.in->sin_addr.s_addr);
  448.  
  449.         lsock.address = local.in->sin_addr.s_addr;
  450.         lsock.port = local.in->sin_port;
  451.         fsock.address = remote.in->sin_addr.s_addr;
  452.         fsock.port = remote.in->sin_port;
  453.  
  454.         /* Open the TCB in active mode */
  455.         up->cb.tcb = open_tcp(&lsock,&fsock,TCP_ACTIVE,0,
  456.          s_trcall,s_ttcall,s_tscall,0,s);
  457.  
  458.         /* Wait for the connection to complete */
  459.         while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != TCP_ESTABLISHED){
  460. #ifdef useblock
  461.             if(up->noblock){
  462.                 errno = EWOULDBLOCK;
  463.                 return -1;
  464.             } else
  465. #endif
  466.                 if((errno = pwait(up)) != 0){
  467.                 return -1;
  468.             }
  469.         }
  470.         if(cb.tcb == NULLTCB){
  471.             /* Probably got refused */
  472.             free(up->peername);
  473.             up->peername = NULLCHAR;
  474.             errno = ECONNREFUSED;
  475.             return -1;
  476.         }
  477.         break;
  478.     case TYPE_UDP:
  479. #ifdef    AX25
  480.     case TYPE_AX25UI:
  481. #endif
  482. #ifdef    NETROM
  483.     case TYPE_NETROML3:
  484. #endif
  485.     case TYPE_RAW:
  486.         /* Control block already created by bind() */
  487.         break;
  488. #ifdef    AX25
  489.     case TYPE_AX25I:
  490.         local.ax = (struct sockaddr_ax *)up->name;
  491.         remote.ax = (struct sockaddr_ax *)up->peername;
  492.         if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  493.             errno = EINVAL;
  494.             return -1;
  495.         }
  496.         if(local.ax->ax25_addr[0] == '\0'){
  497.             /* The local address was unspecified; set it from
  498.              * the interface address
  499.              */
  500.             memcpy(local.ax->ax25_addr,iface->hwaddr,AXALEN);
  501.         }
  502.         /* If we already have an AX25 link we can use it */
  503.         if((up->cb.ax25 = find_ax25(local.ax->ax25_addr, \
  504.                                     remote.ax->ax25_addr,iface)) != NULLAX25
  505.            && up->cb.ax25->state != LAPB_DISCONNECTED &&
  506.            up->cb.ax25->user == -1) {
  507.             up->cb.ax25->user = s;
  508.             up->cb.ax25->r_upcall = s_arcall;
  509.             up->cb.ax25->t_upcall = s_atcall;
  510.             up->cb.ax25->s_upcall = s_ascall;
  511.             if(up->cb.ax25->state == LAPB_CONNECTED
  512.                || up->cb.ax25->state == LAPB_RECOVERY)
  513.                     return 0;
  514.         } else
  515.             up->cb.ax25 = open_ax25(iface,local.ax->ax25_addr,
  516.              remote.ax->ax25_addr,AX_ACTIVE,
  517.              Axwindow,s_arcall,s_atcall,s_ascall,s);
  518.  
  519.         /* Wait for the connection to complete */
  520.         while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != LAPB_CONNECTED){
  521. #ifdef useblock
  522.             if(up->noblock){
  523.                 errno = EWOULDBLOCK;
  524.                 return -1;
  525.             } else
  526. #endif
  527.                 if((errno = pwait(up)) != 0){
  528.                 return -1;
  529.             }
  530.         }
  531.         if(cb.ax25 == NULLAX25){
  532.             /* Connection probably already exists */
  533.             free(up->peername);
  534.             up->peername = NULLCHAR;
  535.             errno = ECONNREFUSED;
  536.             return -1;
  537.         }
  538.         break;
  539. #endif
  540. #ifdef    NETROM
  541.     case TYPE_NETROML4:
  542.         local.nr = (struct sockaddr_nr *)up->name;
  543.         remote.nr = (struct sockaddr_nr *)up->peername;
  544.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,&remote.nr->nr_addr,
  545.          AX_ACTIVE,s_nrcall,s_ntcall,s_nscall,s);
  546.  
  547.         /* Wait for the connection to complete */
  548.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB && cb.nr4->state != NR4STCON){
  549. #ifdef useblock
  550.             if(up->noblock){
  551.                 errno = EWOULDBLOCK;
  552.                 return -1;
  553.             } else
  554. #endif
  555.                 if((errno = pwait(up)) != 0){
  556.                 return -1;
  557.             }
  558.         }
  559.         if(cb.nr4 == NULLNR4CB){
  560.             /* Connection probably already exists */
  561.             free(up->peername);
  562.             up->peername = NULLCHAR;
  563.             errno = ECONNREFUSED;
  564.             return -1;
  565.         }
  566.         break;
  567. #endif
  568.     }
  569.     return 0;
  570. }
  571. /* Wait for a connection. Valid only for connection-oriented sockets. */
  572. int
  573. accept(s,peername,peernamelen)
  574. int s;            /* Socket index */
  575. char *peername;        /* Peer name */
  576. int *peernamelen;    /* Length of peer name */
  577. {
  578.     int i;
  579.     register struct usock *up;
  580.  
  581.     if((up = itop(s)) == NULLUSOCK){
  582.         errno = EBADF;
  583.         return -1;
  584.     }
  585.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  586.         errno = EINVAL;
  587.         return -1;
  588.     }
  589.     if(up->cb.p == NULLCHAR){
  590.         errno = EOPNOTSUPP;
  591.         return -1;
  592.     }
  593.     /* Accept is valid only for stream sockets */
  594.     switch(up->type){
  595.     case TYPE_TCP:
  596. #ifdef    AX25
  597.     case TYPE_AX25I:
  598. #endif
  599. #ifdef    NETROM
  600.     case TYPE_NETROML4:
  601. #endif
  602.         break;
  603.     default:
  604.         errno = EOPNOTSUPP;
  605.         return -1;
  606.     }    
  607.     /* Wait for the state-change upcall routine to signal us */
  608.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  609. #ifdef useblock
  610.         if(up->noblock){
  611.             errno = EWOULDBLOCK;
  612.             return -1;
  613.         } else
  614. #endif
  615.             if((errno = pwait(up)) != 0){
  616.             return -1;
  617.         }
  618.     }
  619.     if(up->cb.p == NULLCHAR){
  620.         /* Blown away */
  621.         errno = EBADF;
  622.         return -1;
  623.     }
  624.     i = up->rdysock;
  625.     up->rdysock = -1;
  626.  
  627.     up = itop(i);
  628.     if(peername != NULLCHAR && peernamelen != NULL){
  629.         *peernamelen = min(up->peernamelen,*peernamelen);
  630.         memcpy(peername,up->peername,(size_t)*peernamelen);
  631.     }
  632.     /* set the time this was created - WG7J */
  633.     up->created = time(NULL);
  634.     return i;
  635. }
  636. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  637.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  638.  * the len parameter.
  639.  */
  640. int
  641. recv_mbuf(s,bpp,flags,from,fromlen)
  642. int s;            /* Socket index */
  643. struct mbuf **bpp;    /* Place to stash receive buffer */
  644. int flags;        /* Unused; will control out-of-band data, etc */
  645. char *from;        /* Peer address (only for datagrams) */
  646. int *fromlen;        /* Length of peer address */
  647. {
  648.     register struct usock *up;
  649.     int cnt;
  650.     union cb cb;
  651.     struct socket fsocket;
  652. #ifdef    NETROM
  653.     struct nr3hdr n3hdr;
  654. #endif
  655.     union sp remote;
  656.     struct ip ip;
  657.     struct mbuf *bp;
  658.  
  659.     if((up = itop(s)) == NULLUSOCK){
  660.         errno = EBADF;
  661.         return -1;
  662.     }
  663.     if(up->ibuf != NULLBUF){
  664.         /* Return input buffer */
  665.         cnt = len_p(up->ibuf);
  666.         if(bpp != NULLBUFP)
  667.             *bpp = up->ibuf;
  668.         else
  669.             free_p(up->ibuf);
  670.         up->ibuf = NULLBUF;        
  671.         return cnt;
  672.     }
  673. #ifdef __GNUC__
  674.     cnt = 0;    /* silence warning */
  675. #endif
  676.     switch(up->type){
  677.     case TYPE_LOCAL_STREAM:
  678.     case TYPE_LOCAL_DGRAM:
  679.         while(up->cb.local != NULLLOC && up->cb.local->q == NULLBUF
  680.               && up->cb.local->peer != NULLUSOCK){
  681. #ifdef useblock
  682.             if(up->noblock){
  683.                 errno = EWOULDBLOCK;
  684.                 return -1;
  685.             } else
  686. #endif
  687.                 if((errno = pwait(up)) != 0){
  688.                 return -1;
  689.             }
  690.         }
  691.         if(up->cb.local == NULLLOC){
  692.             errno = EBADF;
  693.             return -1;
  694.         }
  695.         if(up->cb.local->q == NULLBUF &&
  696.            up->cb.local->peer == NULLUSOCK){
  697.             errno = ENOTCONN;
  698.             return -1;
  699.         }
  700.         /* For datagram sockets, this will return the
  701.          * first packet on the queue. For stream sockets,
  702.          * this will return everything.
  703.          */
  704.         bp = dequeue(&up->cb.local->q);
  705.         if(up->cb.local->q == NULLBUF
  706.          && (up->cb.local->flags & LOC_SHUTDOWN))
  707.             close_s(s);
  708.         psignal(up,0);
  709.         cnt = len_p(bp);
  710.         break;
  711.     case TYPE_TCP:
  712.         while((cb.tcb = up->cb.tcb) != NULLTCB
  713.          && cb.tcb->r_upcall != trdiscard
  714.                  && (cnt = recv_tcp(cb.tcb,&bp,(int16)0)) == -1){
  715. #ifdef useblock
  716.             if(up->noblock){
  717.                 errno = EWOULDBLOCK;
  718.                 return -1;
  719.             } else
  720. #endif
  721.                 if((errno = pwait(up)) != 0){
  722.                 return -1;
  723.             }
  724.         }
  725.         if(cb.tcb == NULLTCB){
  726.             /* Connection went away */
  727.             errno = ENOTCONN;
  728.             return -1;
  729.         } else if(cb.tcb->r_upcall == trdiscard){
  730.             /* Receive shutdown has been done */
  731.             errno = ENOTCONN;    /* CHANGE */
  732.             return -1;
  733.         }
  734.         break;
  735.     case TYPE_UDP:
  736.         while((cb.udp = up->cb.udp) != NULLUDP
  737.         && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  738. #ifdef useblock
  739.             if(up->noblock){
  740.                 errno = EWOULDBLOCK;
  741.                 return -1;
  742.             } else
  743. #endif
  744.                 if((errno = pwait(up)) != 0){
  745.                 return -1;
  746.             }
  747.         }
  748.         if(cb.udp == NULLUDP){
  749.             /* Connection went away */
  750.             errno = ENOTCONN;
  751.             return -1;
  752.         }
  753.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  754.             remote.in = (struct sockaddr_in *)from;
  755.             remote.in->sin_family = AF_INET;
  756.             remote.in->sin_addr.s_addr = fsocket.address;
  757.             remote.in->sin_port = fsocket.port;
  758.             *fromlen = SOCKSIZE;
  759.         }
  760.         break;
  761.     case TYPE_RAW:
  762.         while((cb.rip = up->cb.rip) != NULLRIP
  763.          && cb.rip->rcvq == NULLBUF){
  764. #ifdef useblock
  765.             if(up->noblock){
  766.                 errno = EWOULDBLOCK;
  767.                 return -1;
  768.             } else
  769. #endif
  770.                 if((errno = pwait(up)) != 0){
  771.                 return -1;
  772.             }
  773.         }
  774.         if(cb.rip == NULLRIP){
  775.             /* Connection went away */
  776.             errno = ENOTCONN;
  777.             return -1;
  778.         }
  779.         bp = dequeue(&cb.rip->rcvq);
  780.         ntohip(&ip,&bp);
  781.  
  782.         cnt = len_p(bp);
  783.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  784.             remote.in = (struct sockaddr_in *)from;
  785.             remote.in->sin_family = AF_INET;
  786.             remote.in->sin_addr.s_addr = ip.source;
  787.             remote.in->sin_port = 0;
  788.             *fromlen = SOCKSIZE;
  789.         }
  790.         break;
  791. #ifdef    AX25
  792.     case TYPE_AX25I:
  793.         while((cb.ax25 = up->cb.ax25) != NULLAX25
  794.          && (bp = recv_ax25(cb.ax25,(int16)0)) == NULLBUF){
  795. #ifdef useblock
  796.             if(up->noblock){
  797.                 errno = EWOULDBLOCK;
  798.                 return -1;
  799.             } else
  800. #endif
  801.                 if((errno = pwait(up)) != 0){
  802.                 return -1;
  803.             }
  804.         }
  805.         if(cb.ax25 == NULLAX25){
  806.             /* Connection went away */
  807.             errno = ENOTCONN;
  808.             return -1;
  809.         }
  810.         cnt = bp->cnt;
  811.         break;
  812. #ifdef notdef
  813.     case TYPE_AX25UI:
  814.         while(s == Axui_sock && Bcq == NULLBUF){
  815. #ifdef useblock
  816.             if(up->noblock){
  817.                 errno = EWOULDBLOCK;
  818.                 return -1;
  819.             } else
  820. #endif
  821.                 if((errno = pwait(&Bcq)) != 0){
  822.                 return -1;
  823.             }
  824.         }
  825.         if(s != Axui_sock){
  826.             errno = ENOTCONN;
  827.             return -1;
  828.         }
  829.         bp = dequeue(&Bcq);
  830.  
  831.         if(from != NULLCHAR && fromlen != NULLINT
  832.            && *fromlen >= sizeof(struct sockaddr_ax)){
  833.             pullup(&bp,from,sizeof(struct sockaddr_ax));
  834.             *fromlen = sizeof(struct sockaddr_ax);
  835.         } else {
  836.             pullup(&bp,NULLCHAR,sizeof(struct sockaddr_ax));
  837.         }
  838.         cnt = len_p(bp);
  839.         break;
  840. #endif /* notdef */
  841. #endif /* ax25 */
  842. #ifdef NETROM
  843.     case TYPE_NETROML3:
  844.         while((cb.rnr = up->cb.rnr) != NULLRNR
  845.          && cb.rnr->rcvq == NULLBUF){
  846. #ifdef useblock
  847.             if(up->noblock){
  848.                 errno = EWOULDBLOCK;
  849.                 return -1;
  850.             } else
  851. #endif
  852.                 if((errno = pwait(up)) != 0){
  853.                 return -1;
  854.             }
  855.         }
  856.         if(cb.rnr == NULLRNR){
  857.             /* Connection went away */
  858.             errno = ENOTCONN;
  859.             return -1;
  860.         }
  861.         bp = dequeue(&cb.rnr->rcvq);
  862.         ntohnr3(&n3hdr,&bp);
  863.         cnt = len_p(bp);
  864.         if(from != NULLCHAR && fromlen != NULLINT
  865.            && *fromlen >= sizeof(struct sockaddr_nr)){
  866.             remote.nr = (struct sockaddr_nr *)from;
  867.             remote.nr->nr_family = AF_NETROM;
  868.             /* The callsign of the local user is not part of
  869.                NET/ROM level 3, so that field is not used here */
  870.             memcpy(remote.nr->nr_addr.node,n3hdr.source,AXALEN);
  871.             *fromlen = sizeof(struct sockaddr_nr);
  872.         }
  873.         break;
  874.     case TYPE_NETROML4:
  875.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB
  876.          && (bp = recv_nr4(cb.nr4,(int16)0)) == NULLBUF){
  877. #ifdef useblock
  878.             if(up->noblock){
  879.                 errno = EWOULDBLOCK;
  880.                 return -1;
  881.             } else
  882. #endif
  883.                 if((errno = pwait(up)) != 0){
  884.                 return -1;
  885.             }
  886.         }
  887.         if(cb.nr4 == NULLNR4CB){
  888.             /* Connection went away */
  889.             errno = ENOTCONN;
  890.             return -1;
  891.         }
  892.         cnt = bp->cnt;
  893.         break;
  894. #endif
  895.     }
  896.     if(bpp != NULLBUFP)
  897.         *bpp = bp;
  898.     else
  899.         free_p(bp);
  900.     return cnt;
  901. }
  902. /* Low level send routine; user supplies mbuf for transmission. More
  903.  * efficient than send() or sendto(), the higher level interfaces.
  904.  * The "to" and "tolen" parameters are ignored on connection-oriented
  905.  * sockets.
  906.  *
  907.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  908.  */
  909. int
  910. send_mbuf(s,bp,flags,to,tolen)
  911. int s;            /* Socket index */
  912. struct mbuf *bp;    /* Buffer to send */
  913. int flags;        /* not currently used */
  914. char *to;        /* Destination, only for datagrams */
  915. int tolen;        /* Length of destination */
  916. {
  917.     register struct usock *up;
  918.     union cb cb;
  919.     union sp local,remote;
  920.     struct socket lsock,fsock;
  921.     int cnt;
  922.  
  923.     if((up = itop(s)) == NULLUSOCK){
  924.         free_p(bp);
  925.         errno = EBADF;
  926.         return -1;
  927.     }
  928. #ifndef    notdef
  929.     if(up->obuf != NULLBUF){
  930.         /* If there's unflushed output, send it.
  931.          * Note the importance of clearing up->obuf
  932.          * before the recursive call!
  933.          */
  934.         struct mbuf *bp1;
  935.  
  936.         bp1 = up->obuf;
  937.         up->obuf = NULLBUF;
  938.         send_mbuf(s,bp1,flags,to,tolen);
  939.     }
  940. #endif
  941.     if(up->name == NULLCHAR){
  942.         /* Automatic local name assignment for datagram sockets */
  943.         switch(up->type){
  944.         case TYPE_LOCAL_STREAM:
  945.         case TYPE_LOCAL_DGRAM:
  946.             break;    /* no op */
  947.         case TYPE_UDP:
  948.         case TYPE_RAW:
  949.             autobind(s,AF_INET);
  950.             break;
  951. #ifdef    AX25
  952.         case TYPE_AX25UI:
  953.             autobind(s,AF_AX25);
  954.             break;
  955. #endif
  956. #ifdef    NETROM
  957.         case TYPE_NETROML3:
  958.         case TYPE_NETROML4:
  959.             autobind(s,AF_NETROM);
  960.             break;
  961. #endif
  962.         default:
  963.             free_p(bp);
  964.             errno = ENOTCONN;
  965.             return -1;
  966.         }
  967.     }
  968.     cnt = len_p(bp);
  969.     switch(up->type){
  970.     case TYPE_LOCAL_DGRAM:
  971.         if(up->cb.local->peer == NULLUSOCK){
  972.             free_p(bp);
  973.             errno = ENOTCONN;
  974.             return -1;
  975.         }
  976.         enqueue(&up->cb.local->peer->cb.local->q,bp);
  977.         psignal(up->cb.local->peer,0);
  978.         /* If high water mark has been reached, block */
  979.         while(up->cb.local->peer != NULLUSOCK &&
  980.               len_q(up->cb.local->peer->cb.local->q) >=
  981.               up->cb.local->peer->cb.local->hiwat){
  982.             if(up->noblock){
  983.                 errno = EWOULDBLOCK;
  984.                 return -1;
  985.             } else if((errno = pwait(up->cb.local->peer)) != 0){
  986.                 return -1;
  987.             }
  988.         }
  989.         if(up->cb.local->peer == NULLUSOCK){
  990.             errno = ENOTCONN;
  991.             return -1;
  992.         }
  993.         break;
  994.     case TYPE_LOCAL_STREAM:
  995.         if(up->cb.local->peer == NULLUSOCK){
  996.             free_p(bp);
  997.             errno = ENOTCONN;
  998.             return -1;
  999.         }
  1000.         append(&up->cb.local->peer->cb.local->q,bp);
  1001.         psignal(up->cb.local->peer,0);
  1002.         /* If high water mark has been reached, block */
  1003.         while(up->cb.local->peer != NULLUSOCK &&
  1004.               len_p(up->cb.local->peer->cb.local->q) >=
  1005.               up->cb.local->peer->cb.local->hiwat){
  1006.             if(up->noblock){
  1007.                 errno = EWOULDBLOCK;
  1008.                 return -1;
  1009.             } else if((errno = pwait(up->cb.local->peer)) != 0){
  1010.                 return -1;
  1011.             }
  1012.         }
  1013.         if(up->cb.local->peer == NULLUSOCK){
  1014.             errno = ENOTCONN;
  1015.             return -1;
  1016.         }
  1017.         break;
  1018.     case TYPE_TCP:
  1019.         if((cb.tcb = up->cb.tcb) == NULLTCB){
  1020.             free_p(bp);
  1021.             errno = ENOTCONN;
  1022.             return -1;
  1023.         }        
  1024.         cnt = send_tcp(cb.tcb,bp);
  1025.  
  1026.         while((cb.tcb = up->cb.tcb) != NULLTCB &&
  1027.          cb.tcb->sndcnt > cb.tcb->window){
  1028.             /* Send queue is full */
  1029.             if(up->noblock){
  1030.                 errno = EWOULDBLOCK;
  1031.                 return -1;
  1032.             } else if((errno = pwait(up)) != 0){
  1033.                 return -1;
  1034.             }
  1035.         }
  1036.          if(cb.tcb == NULLTCB){
  1037.             errno = ENOTCONN;
  1038.             return -1;
  1039.         }
  1040.         break;
  1041.     case TYPE_UDP:
  1042.         local.in = (struct sockaddr_in *)up->name;
  1043.         lsock.address = local.in->sin_addr.s_addr;
  1044.         lsock.port = local.in->sin_port;
  1045.         if(to != NULLCHAR)
  1046.             remote.in = (struct sockaddr_in *)to;
  1047.         else if(up->peername != NULLCHAR)
  1048.             remote.in = (struct sockaddr_in *)up->peername;
  1049.         else {
  1050.             errno = ENOTCONN;
  1051.             return -1;
  1052.         }    
  1053.         fsock.address = remote.in->sin_addr.s_addr;
  1054.         fsock.port = remote.in->sin_port;
  1055.         send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  1056.         break;
  1057.     case TYPE_RAW:
  1058.         local.in = (struct sockaddr_in *)up->name;
  1059.         if(to != NULLCHAR)
  1060.             remote.in = (struct sockaddr_in *)to;
  1061.         else if(up->peername != NULLCHAR)
  1062.             remote.in = (struct sockaddr_in *)up->peername;
  1063.         else {
  1064.             errno = ENOTCONN;
  1065.             return -1;
  1066.         }    
  1067.         ip_send((int32)local.in->sin_addr.s_addr,(int32)remote.in->sin_addr.s_addr,
  1068.             (char)up->cb.rip->protocol,0,0,bp,0,0,0);
  1069.         break;
  1070. #ifdef    AX25
  1071.     case TYPE_AX25I:
  1072.         if((cb.ax25 = up->cb.ax25) == NULLAX25){
  1073.             free_p(bp);
  1074.             errno = ENOTCONN;
  1075.             return -1;
  1076.         }
  1077.         send_ax25(cb.ax25,bp,PID_NO_L3);
  1078.  
  1079.         while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  1080.          len_q(cb.ax25->txq) * cb.ax25->paclen > cb.ax25->window){
  1081.             if(up->noblock){
  1082.                 errno = EWOULDBLOCK;
  1083.                 return -1;
  1084.             } else if((errno = pwait(up)) != 0){
  1085.                 return -1;
  1086.             }
  1087.         }
  1088.         if(cb.ax25 == NULLAX25){
  1089.             errno = EBADF;
  1090.             return -1;
  1091.         }
  1092.         break;
  1093.     case TYPE_AX25UI:
  1094.         local.ax = (struct sockaddr_ax *)up->name;
  1095.         if(to != NULLCHAR)
  1096.             remote.ax = (struct sockaddr_ax *)to;
  1097.         else if(up->peername != NULLCHAR)
  1098.             remote.ax = (struct sockaddr_ax *)up->peername;
  1099.         else {
  1100.             errno = ENOTCONN;
  1101.             return -1;
  1102.         }
  1103.         ax_output(if_lookup(remote.ax->iface),
  1104.               remote.ax->ax25_addr,
  1105.               local.ax->ax25_addr,PID_NO_L3,bp);
  1106.         break;
  1107. #endif
  1108. #ifdef NETROM
  1109.     case TYPE_NETROML3:
  1110.         /* This should never happen, since the TCP code will peek at the
  1111.          * interface mtu ! - WG7J
  1112.          */
  1113.         if(len_p(bp) > NR4MAXINFO) {
  1114.             free_p(bp);
  1115.             errno = EMSGSIZE;
  1116.             return -1;
  1117.         }
  1118.         local.nr = (struct sockaddr_nr *)up->name;
  1119.         if(to != NULLCHAR)
  1120.             remote.nr = (struct sockaddr_nr *)to;
  1121.         else if(up->peername != NULLCHAR)
  1122.             remote.nr = (struct sockaddr_nr *)up->peername;
  1123.         else {
  1124.             errno = ENOTCONN;
  1125.             return -1;
  1126.         }    
  1127.         /* The NETROM username is always ignored in outgoing traffic */
  1128.         nr_sendraw(remote.nr->nr_addr.node,
  1129.         (unsigned) up->cb.rnr->protocol,(unsigned)up->cb.rnr->protocol,bp);
  1130.         break;
  1131.     case TYPE_NETROML4:
  1132.         if((cb.nr4 = up->cb.nr4) == NULLNR4CB) {
  1133.             free_p(bp);
  1134.             errno = ENOTCONN;
  1135.             return -1;
  1136.         }
  1137. #ifdef notdef
  1138.         /* since I now fragment nr4 packets in send_nr4(),
  1139.          * don't worry, be happy :-) - WG7J
  1140.          */
  1141.         if(len_p(bp) > NR4MAXINFO){ /* reject big packets */
  1142.             free_p(bp);
  1143.             errno = EMSGSIZE;
  1144.             return -1;
  1145.         }
  1146. #endif
  1147.         send_nr4(cb.nr4,bp);
  1148.  
  1149.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB &&
  1150.          cb.nr4->nbuffered >= cb.nr4->window){
  1151.             if(up->noblock){
  1152.                 errno = EWOULDBLOCK;
  1153.                 return -1;
  1154.             } else if((errno = pwait(up)) != 0){
  1155.                 errno = EINTR;
  1156.                 return -1;
  1157.             }
  1158.         }
  1159.         if(cb.nr4 == NULLNR4CB){
  1160.             errno = EBADF;
  1161.             return -1;
  1162.         }
  1163.         break;
  1164. #endif
  1165.     }    
  1166.     return cnt;
  1167. }
  1168. /* Return local name passed in an earlier bind() call */
  1169. int
  1170. getsockname(s,name,namelen)
  1171. int s;        /* Socket index */
  1172. char *name;    /* Place to stash name */
  1173. int *namelen;    /* Length of same */
  1174. {
  1175.     register struct usock *up;
  1176.  
  1177.     if((up = itop(s)) == NULLUSOCK){
  1178.         errno = EBADF;
  1179.         return -1;
  1180.     }
  1181.     if(name == NULLCHAR || namelen == (int *)NULL){
  1182.         errno = EFAULT;
  1183.         return -1;
  1184.     }
  1185.     if(up->name == NULLCHAR){
  1186.         /* Not bound yet */
  1187.         *namelen = 0;
  1188.         return 0;
  1189.     }
  1190.     if(up->name != NULLCHAR){
  1191.         *namelen = min(*namelen,up->namelen);
  1192.         memcpy(name,up->name,(size_t)*namelen);
  1193.     }
  1194.     return 0;
  1195. }
  1196. /* Get remote name, returning result of earlier connect() call. */
  1197. int
  1198. getpeername(s,peername,peernamelen)
  1199. int s;            /* Socket index */
  1200. char *peername;        /* Place to stash name */
  1201. int *peernamelen;    /* Length of same */
  1202. {
  1203.     register struct usock *up;
  1204.  
  1205.     if((up = itop(s)) == NULLUSOCK){
  1206.         errno = EBADF;
  1207.         return -1;
  1208.     }
  1209.     if(up->peername == NULLCHAR){
  1210.         errno = ENOTCONN;
  1211.         return -1;
  1212.     }
  1213.     if(peername == NULLCHAR || peernamelen == (int *)NULL){
  1214.         errno = EFAULT;
  1215.         return -1;
  1216.     }
  1217.     *peernamelen = min(*peernamelen,up->peernamelen);
  1218.     memcpy(peername,up->peername,(size_t)*peernamelen);
  1219.     return 0;
  1220. }
  1221. /* Return length of protocol queue, either send or receive. */
  1222. int
  1223. socklen(s,rtx)
  1224. int s;        /* Socket index */
  1225. int rtx;    /* 0 = receive queue, 1 = transmit queue */
  1226. {
  1227.     register struct usock *up;
  1228.     int len = -1;
  1229.  
  1230.     if((up = itop(s)) == NULLUSOCK){
  1231.         errno = EBADF;
  1232.         return -1;
  1233.     }
  1234.     if(up->cb.p == NULLCHAR){
  1235.         errno = ENOTCONN;
  1236.         return -1;
  1237.     }
  1238.     if(rtx < 0 || rtx > 1){
  1239.         errno = EINVAL;
  1240.         return -1;
  1241.     }
  1242.     switch(up->type){
  1243.     case TYPE_LOCAL_DGRAM:
  1244.         switch(rtx){
  1245.         case 0:
  1246.             len = len_q(up->cb.local->q);
  1247.             break;
  1248.         case 1:
  1249.             if(up->cb.local->peer != NULLUSOCK)
  1250.                 len = len_q(up->cb.local->peer->cb.local->q);
  1251.             break;
  1252.         }
  1253.         break;
  1254.     case TYPE_LOCAL_STREAM:
  1255.         switch(rtx){
  1256.         case 0:
  1257.             len = len_p(up->cb.local->q) + len_p(up->ibuf);
  1258.             break;
  1259.         case 1:
  1260.             if(up->cb.local->peer != NULLUSOCK)
  1261.                 len = len_p(up->cb.local->peer->cb.local->q)
  1262.                       + len_p(up->obuf);
  1263.             break;
  1264.         }
  1265.         break;
  1266.     case TYPE_TCP:
  1267.         switch(rtx){
  1268.         case 0:
  1269.             len = up->cb.tcb->rcvcnt + len_p(up->ibuf);
  1270.             break;
  1271.         case 1:
  1272.             len = up->cb.tcb->sndcnt + len_p(up->obuf);
  1273.             break;
  1274.         }
  1275.         break;
  1276.     case TYPE_UDP:
  1277.         switch(rtx){
  1278.         case 0:
  1279.             len = up->cb.udp->rcvcnt;
  1280.             break;
  1281.         case 1:
  1282.             len = 0;
  1283.             break;
  1284.         }
  1285.         break;
  1286. #ifdef    AX25
  1287.     case TYPE_AX25I:
  1288.         switch(rtx){
  1289.         case 0:
  1290.             len = len_p(up->cb.ax25->rxq) + len_p(up->ibuf);
  1291.             break;
  1292.         case 1:    /* Number of packets, not bytes */
  1293.             len = len_q(up->cb.ax25->txq);
  1294.             if(up->obuf != NULLBUF)
  1295.                 len++;
  1296.         }
  1297.         break;
  1298. #ifdef notdef
  1299.     case TYPE_AX25UI:
  1300.         switch(rtx){    
  1301.         case 0:
  1302.             len = len_q(Bcq);
  1303.             break;
  1304.         case 1:
  1305.             len = 0;        
  1306.             break;
  1307.         }
  1308.         break;
  1309. #endif /* notdef */
  1310. #endif
  1311. #ifdef NETROM
  1312.     case TYPE_NETROML3:
  1313.         switch(rtx){    
  1314.         case 0:
  1315.             len = len_q(up->cb.rnr->rcvq);
  1316.             break;
  1317.         case 1:
  1318.             len = 0;        
  1319.         }
  1320.         break;
  1321.     case TYPE_NETROML4:
  1322.         switch(rtx){
  1323.         case 0:
  1324.             len = len_p(up->cb.nr4->rxq) + len_p(up->ibuf);
  1325.             break;
  1326.         case 1:    /* Number of packets, not bytes */
  1327.             len = len_q(up->cb.nr4->txq);
  1328.             if(up->obuf != NULLBUF)
  1329.                 len++;
  1330.             break;
  1331.         }
  1332.         break;
  1333. #endif
  1334.     case TYPE_RAW:
  1335.         switch(rtx){    
  1336.         case 0:
  1337.             len = len_q(up->cb.rip->rcvq);
  1338.             break;
  1339.         case 1:
  1340.             len = 0;        
  1341.             break;
  1342.         }
  1343.         break;
  1344.     }
  1345.     return len;
  1346. }
  1347. /* Force retransmission. Valid only for connection-oriented sockets. */
  1348. int
  1349. sockkick(s)
  1350. int s;    /* Socket index */
  1351. {
  1352.     register struct usock *up;
  1353.  
  1354.     if((up = itop(s)) == NULLUSOCK){
  1355.         errno = EBADF;
  1356.         return -1;
  1357.     }
  1358.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  1359.         errno = EINVAL;
  1360.         return -1;
  1361.     }
  1362.     if(up->cb.p == NULLCHAR){
  1363.         errno = ENOTCONN;
  1364.         return -1;
  1365.     }
  1366.     switch(up->type){
  1367.     case TYPE_TCP:
  1368.         kick_tcp(up->cb.tcb);
  1369.         break;
  1370. #ifdef    AX25
  1371.     case TYPE_AX25I:
  1372.         kick_ax25(up->cb.ax25);
  1373.         break;
  1374. #endif
  1375. #ifdef NETROM
  1376.     case TYPE_NETROML4:
  1377.         kick_nr4(up->cb.nr4);
  1378.         break;
  1379. #endif
  1380.     default:
  1381.         /* Datagram sockets can't be kicked */
  1382.         errno = EOPNOTSUPP;
  1383.         return -1;
  1384.     }
  1385.     return 0;
  1386. }
  1387.  
  1388. /* Change owner of socket, return previous owner */
  1389. struct proc *
  1390. sockowner(s,newowner)
  1391. int s;            /* Socket index */
  1392. struct proc *newowner;    /* Process table address of new owner */
  1393. {
  1394.     register struct usock *up;
  1395.     struct proc *pp;
  1396.  
  1397.     if((up = itop(s)) == NULLUSOCK){
  1398.         errno = EBADF;
  1399.         return NULLPROC;
  1400.     }
  1401.     pp = up->owner;
  1402.     if(newowner != NULLPROC)
  1403.         up->owner = newowner;
  1404.     return pp;
  1405. }
  1406. /* Close down a socket three ways. Type 0 means "no more receives"; this
  1407.  * replaces the incoming data upcall with a routine that discards further
  1408.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  1409.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  1410.  * as "abort the connection".
  1411.  */
  1412. int
  1413. shutdown(s,how)
  1414. int s;        /* Socket index */
  1415. int how;    /* (see above) */
  1416. {
  1417.     register struct usock *up;
  1418.  
  1419.     if((up = itop(s)) == NULLUSOCK){
  1420.         errno = EBADF;
  1421.         return -1;
  1422.     }
  1423.     if(up->cb.p == NULLCHAR){
  1424.         errno = ENOTCONN;
  1425.         return -1;
  1426.     }
  1427.     switch(up->type){
  1428.     case TYPE_LOCAL_DGRAM:
  1429.     case TYPE_LOCAL_STREAM:
  1430.         if(up->cb.local->q == NULLBUF)
  1431.             close_s(s);
  1432.         else
  1433.             up->cb.local->flags = LOC_SHUTDOWN;
  1434.         break;
  1435.     case TYPE_TCP:
  1436.         switch(how){
  1437.         case 0:    /* No more receives -- replace upcall */
  1438.             up->cb.tcb->r_upcall = trdiscard;
  1439.             break;
  1440.         case 1:    /* Send EOF */
  1441.             close_tcp(up->cb.tcb);
  1442.             break;
  1443.         case 2:    /* Blow away TCB */
  1444.             reset_tcp(up->cb.tcb);
  1445.             up->cb.tcb = NULLTCB;
  1446.             break;
  1447.         }
  1448.         break;
  1449. #ifdef    AX25
  1450. #ifdef notdef
  1451.     case TYPE_AX25UI:
  1452.         close_s(s);
  1453.         break;
  1454. #endif
  1455.     case TYPE_AX25I:
  1456.         switch(how){
  1457.         case 0:
  1458.         case 1:    /* Attempt regular disconnect */
  1459.             disc_ax25(up->cb.ax25);
  1460.             break;
  1461.         case 2: /* Blow it away */
  1462.             reset_ax25(up->cb.ax25);
  1463.             up->cb.ax25 = NULLAX25;
  1464.             break;
  1465.         }
  1466.         break;        
  1467. #endif
  1468. #ifdef    NETROM
  1469.     case TYPE_NETROML3:
  1470.         close_s(s);
  1471.         break;
  1472.     case TYPE_NETROML4:
  1473.         switch(how){
  1474.         case 0:
  1475.         case 1:    /* Attempt regular disconnect */
  1476.             disc_nr4(up->cb.nr4);
  1477.             break;
  1478.         case 2: /* Blow it away */
  1479.             reset_nr4(up->cb.nr4);
  1480.             up->cb.nr4 = NULLNR4CB;
  1481.             break;
  1482.         }
  1483.         break;        
  1484. #endif
  1485.     case TYPE_RAW:
  1486.     case TYPE_UDP:
  1487.         close_s(s);
  1488.         break;
  1489.     default:
  1490.         errno = EOPNOTSUPP;
  1491.         return -1;
  1492.     }
  1493.     psignal(up,0);
  1494.     return 0;
  1495. }
  1496. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1497.  * TCP socket, if possible
  1498.  */
  1499. int
  1500. close_s(s)
  1501. int s;        /* Socket index */
  1502. {
  1503.     register struct usock *up;
  1504.  
  1505.     if((up = itop(s)) == NULLUSOCK){
  1506.         errno = EBADF;
  1507.         return -1;
  1508.     }
  1509.     if(--up->refcnt > 0)
  1510.         return 0;    /* Others are still using it */
  1511.     usflush(s);
  1512.     if(up->ibuf != NULLBUF){
  1513.         free_p(up->ibuf);
  1514.         up->ibuf = NULLBUF;
  1515.     }
  1516.     switch(up->type){
  1517.     case TYPE_LOCAL_STREAM:
  1518.     case TYPE_LOCAL_DGRAM:
  1519.         if(up->cb.local->peer != NULLUSOCK){
  1520.             up->cb.local->peer->cb.local->peer = NULLUSOCK;
  1521.             psignal(up->cb.local->peer,0);
  1522.         }
  1523.         free_q(&up->cb.local->q);
  1524.         free(up->cb.local);
  1525.         break;
  1526.     case TYPE_TCP:
  1527.         if(up->cb.tcb != NULLTCB){    /* In case it's been reset */
  1528.             up->cb.tcb->r_upcall = trdiscard;
  1529.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1530.             up->cb.tcb->user = -1;
  1531.             close_tcp(up->cb.tcb);
  1532.         }
  1533.         break;
  1534.     case TYPE_UDP:
  1535.         if(up->cb.udp != NULLUDP){
  1536.             del_udp(up->cb.udp);
  1537.         }
  1538.         break;
  1539. #ifdef    AX25
  1540.     case TYPE_AX25I:
  1541.         if(up->cb.ax25 != NULLAX25){
  1542.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1543.             up->cb.ax25->user = -1;
  1544.             disc_ax25(up->cb.ax25);
  1545.         }
  1546.         break;
  1547. #ifdef notdef
  1548.     case TYPE_AX25UI:
  1549.         Axui_sock = -1;
  1550.         free_q(&Bcq);
  1551.         psignal(&Bcq,0);    /* Unblock any reads */
  1552.         break;
  1553. #endif /* notdef */
  1554. #endif
  1555. #ifdef    NETROM
  1556.     case TYPE_NETROML3:
  1557.         del_rnr(up->cb.rnr);
  1558.         break;
  1559.     case TYPE_NETROML4:
  1560.         if(up->cb.nr4 != NULLNR4CB){
  1561.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1562.             up->cb.nr4->user = -1;
  1563.             disc_nr4(up->cb.nr4);
  1564.         }
  1565.         break;
  1566. #endif
  1567.     case TYPE_RAW:
  1568.         del_ip(up->cb.rip);
  1569.         break;
  1570.     default:
  1571.         errno = EOPNOTSUPP;
  1572.         return -1;
  1573.     }
  1574. #ifdef    LZW
  1575.     if(up->zout != NULLLZW || up->zin != NULLLZW)
  1576.         lzwfree(up);
  1577. #endif
  1578.     free(up->name);
  1579.     free(up->peername);
  1580.  
  1581.     up->cb.p = NULLCHAR;
  1582.     up->name = up->peername = NULLCHAR;
  1583.     up->type = NOTUSED;
  1584.     psignal(up,0);    /* Wake up anybody doing an accept() or recv() */
  1585.     return 0;
  1586. }
  1587. /* Increment reference count for specified socket */
  1588. int
  1589. usesock(s)
  1590. int s;
  1591. {
  1592.     struct usock *up;
  1593.  
  1594.     if((up = itop(s)) == NULLUSOCK){
  1595.         errno = EBADF;
  1596.         return -1;
  1597.     }
  1598.     up->refcnt++;
  1599.     return 0;
  1600. }
  1601. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1602. void
  1603. freesock(pp)
  1604. struct proc *pp;
  1605. {
  1606.     register struct usock *up;
  1607.     register int i;
  1608.  
  1609.     for(i=SOCKBASE;i < Nusock+SOCKBASE;i++){
  1610.         up = itop(i);
  1611.         if(up != NULLUSOCK && up->type != NOTUSED && up->owner == pp)
  1612.             shutdown(i,2);
  1613.     }
  1614. }
  1615. /* Start of internal subroutines */
  1616.  
  1617. /* Raw IP receive upcall routine */
  1618. static void
  1619. rip_recv(rp)
  1620. struct raw_ip *rp;
  1621. {
  1622.     psignal(itop(rp->user),1);
  1623.     pwait(NULL);
  1624. }
  1625.  
  1626. /* UDP receive upcall routine */
  1627. static void
  1628. s_urcall(iface,udp,cnt)
  1629. struct iface *iface;
  1630. struct udp_cb *udp;
  1631. int16 cnt;
  1632. {
  1633.     psignal(itop(udp->user),1);
  1634.     pwait(NULL);
  1635. }
  1636. /* TCP receive upcall routine */
  1637. static void
  1638. s_trcall(tcb,cnt)
  1639. struct tcb *tcb;
  1640. int16 cnt;
  1641. {
  1642.     /* Wake up anybody waiting for data, and let them run */
  1643.     psignal(itop(tcb->user),1);
  1644.     pwait(NULL);
  1645. }
  1646. /* TCP transmit upcall routine */
  1647. static void
  1648. s_ttcall(tcb,cnt)
  1649. struct tcb *tcb;
  1650. int16 cnt;
  1651. {
  1652.     /* Wake up anybody waiting to send data, and let them run */
  1653.     psignal(itop(tcb->user),1);
  1654.     pwait(NULL);
  1655. }
  1656. /* TCP state change upcall routine */
  1657. static void
  1658. s_tscall(tcb,old,new)
  1659. struct tcb *tcb;
  1660. int old,new;
  1661. {
  1662.     int s,ns;
  1663.     struct usock *up,*nup,*oup;
  1664.     union sp sp;
  1665.  
  1666.     s = tcb->user;
  1667.     oup = up = itop(s);
  1668.  
  1669.     switch(new){
  1670.     case TCP_CLOSED:
  1671.         /* Clean up. If the user has already closed the socket,
  1672.          * then up will be null (s was set to -1 by the close routine).
  1673.          * If not, then this is an abnormal close (e.g., a reset)
  1674.          * and clearing out the pointer in the socket structure will
  1675.          * prevent any further operations on what will be a freed
  1676.          * control block. Also wake up anybody waiting on events
  1677.          * related to this tcb so they will notice it disappearing.
  1678.          */
  1679.         if(up != NULLUSOCK){
  1680.             up->cb.tcb = NULLTCB;
  1681.             up->errcodes[0] = tcb->reason;
  1682.             up->errcodes[1] = tcb->type;
  1683.             up->errcodes[2] = tcb->code;
  1684.         }
  1685.         del_tcp(tcb);
  1686.         break;
  1687.     case TCP_SYN_RECEIVED:
  1688.         /* Handle an incoming connection. If this is a server TCB,
  1689.          * then we're being handed a "clone" TCB and we need to
  1690.          * create a new socket structure for it. In either case,
  1691.          * find out who we're talking to and wake up the guy waiting
  1692.          * for the connection.
  1693.          */
  1694.         if(tcb->flags.clone){
  1695.             /* Clone the socket */
  1696.             ns = socket(AF_INET,SOCK_STREAM,0);
  1697.             nup = itop(ns);
  1698.             ASSIGN(*nup,*up);
  1699.             tcb->user = ns;
  1700.             nup->cb.tcb = tcb;
  1701.             /* Allocate new memory for the name areas */
  1702.             nup->name = mallocw(SOCKSIZE);
  1703.             nup->peername = mallocw(SOCKSIZE);
  1704.             /* Store the new socket # in the old one */
  1705.             up->rdysock = ns;
  1706.             up = nup;
  1707.             s = ns;
  1708.         } else {
  1709.             /* Allocate space for the peer's name */
  1710.             up->peername = mallocw(SOCKSIZE);
  1711.             /* Store the old socket # in the old socket */
  1712.             up->rdysock = s;
  1713.         }
  1714.         /* Load the addresses. Memory for the name has already
  1715.          * been allocated, either above or in the original bind.
  1716.          */
  1717.         sp.p = up->name;
  1718.         sp.in->sin_family = AF_INET;
  1719.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1720.         sp.in->sin_port = up->cb.tcb->conn.local.port;
  1721.         up->namelen = SOCKSIZE;
  1722.  
  1723.         sp.p = up->peername;
  1724.         sp.in->sin_family = AF_INET;
  1725.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1726.         sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1727.         up->peernamelen = SOCKSIZE;
  1728.  
  1729.         /* Wake up the guy accepting it, and let him run */
  1730.         psignal(oup,1);
  1731.         pwait(NULL);
  1732.         break;
  1733.     default:    /* Ignore all other state transitions */
  1734.         break;
  1735.     }
  1736.     psignal(up,0);    /* In case anybody's waiting */
  1737. }
  1738. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1739.  * close_s until the TCB disappears.
  1740.  */
  1741. static void
  1742. trdiscard(tcb,cnt)
  1743. struct tcb *tcb;
  1744. int cnt;
  1745. {
  1746.     struct mbuf *bp;
  1747.  
  1748.     recv_tcp(tcb,&bp,(int16)cnt);
  1749.     free_p(bp);
  1750. }
  1751. #ifdef    AX25
  1752. /* AX.25 receive upcall */
  1753. void
  1754. s_arcall(axp,cnt)
  1755. struct ax25_cb *axp;
  1756. int cnt;
  1757. {
  1758.     int ns;
  1759.     struct usock *up,*nup,*oup;
  1760.     union sp sp;
  1761.  
  1762.     up = itop(axp->user);
  1763.     /* When AX.25 data arrives for the first time the AX.25 listener
  1764.        is notified, if active. If the AX.25 listener is a server its
  1765.        socket is duplicated in the same manner as in s_tscall().
  1766.      */
  1767.     if (Axi_sock != -1 && axp->user == -1) {
  1768.         oup = up = itop(Axi_sock);
  1769.         /* From now on, use the same upcalls as the listener */
  1770.         axp->t_upcall = up->cb.ax25->t_upcall;
  1771.         axp->r_upcall = up->cb.ax25->r_upcall;
  1772.         axp->s_upcall = up->cb.ax25->s_upcall;
  1773.         if (up->cb.ax25->flags.clone) {
  1774.             /* Clone the socket */
  1775.             ns = socket(AF_AX25,SOCK_STREAM,0);
  1776.             nup = itop(ns);
  1777.             ASSIGN(*nup,*up);
  1778.             axp->user = ns;
  1779.             nup->cb.ax25 = axp;
  1780.             /* Allocate new memory for the name areas */
  1781.             nup->name = mallocw(sizeof(struct sockaddr_ax));
  1782.             nup->peername = mallocw(sizeof(struct sockaddr_ax));
  1783.             /* Store the new socket # in the old one */
  1784.             up->rdysock = ns;
  1785.             up = nup;
  1786.         } else {
  1787.             axp->user = Axi_sock;
  1788.             del_ax25(up->cb.ax25);
  1789.             up->cb.ax25 = axp;
  1790.             /* Allocate space for the peer's name */
  1791.             up->peername = mallocw(sizeof(struct sockaddr_ax));
  1792.             /* Store the old socket # in the old socket */
  1793.             up->rdysock = Axi_sock;
  1794.         }
  1795.         /* Load the addresses. Memory for the name has already
  1796.          * been allocated, either above or in the original bind.
  1797.          */
  1798.         sp.p = up->name;
  1799.         sp.ax->sax_family = AF_AX25;
  1800.         memcpy(sp.ax->ax25_addr,axp->local,AXALEN);
  1801.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1802.         up->namelen = sizeof(struct sockaddr_ax);
  1803.  
  1804.         sp.p = up->peername;
  1805.         sp.ax->sax_family = AF_AX25;
  1806.         memcpy(sp.ax->ax25_addr,axp->remote,AXALEN);
  1807.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1808.         up->peernamelen = sizeof(struct sockaddr_ax);
  1809.         /* Wake up the guy accepting it, and let him run */
  1810.         psignal(oup,1);
  1811.         pwait(NULL);
  1812.         return;
  1813.     }
  1814.     /* Wake up anyone waiting, and let them run */
  1815.     psignal(up,1);
  1816.     pwait(NULL);
  1817. }
  1818. /* AX.25 transmit upcall */
  1819. void
  1820. s_atcall(axp,cnt)
  1821. struct ax25_cb *axp;
  1822. int cnt;
  1823. {
  1824.     /* Wake up anyone waiting, and let them run */
  1825.     psignal(itop(axp->user),1);
  1826.     pwait(NULL);
  1827. }
  1828. /* AX25 state change upcall routine */
  1829. void
  1830. s_ascall(axp,old,new)
  1831. register struct ax25_cb *axp;
  1832. int old,new;
  1833. {
  1834.     int s;
  1835.     struct usock *up;
  1836.  
  1837.     s = axp->user;
  1838.     up = itop(s);
  1839.  
  1840.     switch(new){
  1841.     case LAPB_DISCONNECTED:
  1842.         /* Clean up. If the user has already closed the socket,
  1843.          * then up will be null (s was set to -1 by the close routine).
  1844.          * If not, then this is an abnormal close (e.g., a reset)
  1845.          * and clearing out the pointer in the socket structure will
  1846.          * prevent any further operations on what will be a freed
  1847.          * control block. Also wake up anybody waiting on events
  1848.          * related to this block so they will notice it disappearing.
  1849.          */
  1850.         if(up != NULLUSOCK){
  1851.             up->errcodes[0] = axp->reason;
  1852.             up->cb.ax25 = NULLAX25;
  1853.         }
  1854.         del_ax25(axp);
  1855.         break;
  1856.     default:    /* Other transitions are ignored */
  1857.         break;
  1858.     }
  1859.     psignal(up,0);    /* In case anybody's waiting */
  1860. }
  1861. #endif
  1862. #ifdef NETROM
  1863. /* NET/ROM receive upcall routine */
  1864. static void
  1865. s_nrcall(cb,cnt)
  1866. struct nr4cb *cb;
  1867. int16 cnt;
  1868. {
  1869.     /* Wake up anybody waiting for data, and let them run */
  1870.     psignal(itop(cb->user),1);
  1871.     pwait(NULL);
  1872. }
  1873. /* NET/ROM transmit upcall routine */
  1874. static void
  1875. s_ntcall(cb,cnt)
  1876. struct nr4cb *cb;
  1877. int16 cnt;
  1878. {
  1879.     /* Wake up anybody waiting to send data, and let them run */
  1880. /*    psignal(itop(cb->user),1); */
  1881. /* Quick-fix for sending wait problem - Dave Perry, VE3IFB */
  1882.     psignal(itop(cb->user),0);
  1883.     pwait(NULL);
  1884. }
  1885. /* NET/ROM state change upcall routine */
  1886. static void
  1887. s_nscall(cb,old,new)
  1888. struct nr4cb *cb;
  1889. int old,new;
  1890. {
  1891.     int s,ns;
  1892.     struct usock *up,*nup,*oup;
  1893.     union sp sp;
  1894.  
  1895.     s = cb->user;
  1896.     oup = up = itop(s);
  1897.  
  1898.      if(new == NR4STDISC && up != NULLUSOCK){
  1899.         /* Clean up. If the user has already closed the socket,
  1900.          * then up will be null (s was set to -1 by the close routine).
  1901.          * If not, then this is an abnormal close (e.g., a reset)
  1902.          * and clearing out the pointer in the socket structure will
  1903.          * prevent any further operations on what will be a freed
  1904.          * control block. Also wake up anybody waiting on events
  1905.          * related to this cb so they will notice it disappearing.
  1906.          */
  1907.          up->cb.nr4 = NULLNR4CB;
  1908.          up->errcodes[0] = cb->dreason;
  1909.      }
  1910.      if(new == NR4STCON && old == NR4STDISC){
  1911.         /* Handle an incoming connection. If this is a server cb,
  1912.          * then we're being handed a "clone" cb and we need to
  1913.          * create a new socket structure for it. In either case,
  1914.          * find out who we're talking to and wake up the guy waiting
  1915.          * for the connection.
  1916.          */
  1917.         if(cb->clone){
  1918.             /* Clone the socket */
  1919.             ns = socket(AF_NETROM,SOCK_SEQPACKET,0);
  1920.             nup = itop(ns);
  1921.             ASSIGN(*nup,*up);
  1922.             cb->user = ns;
  1923.             nup->cb.nr4 = cb;
  1924.             cb->clone = 0; /* to avoid getting here again */
  1925.             /* Allocate new memory for the name areas */
  1926.             nup->name = mallocw(sizeof(struct sockaddr_nr));
  1927.             nup->peername = mallocw(sizeof(struct sockaddr_nr));
  1928.             /* Store the new socket # in the old one */
  1929.             up->rdysock = ns;
  1930.             up = nup;
  1931.             s = ns;
  1932.         } else {
  1933.             /* Allocate space for the peer's name */
  1934.             up->peername = mallocw(sizeof(struct sockaddr_nr));
  1935.             /* Store the old socket # in the old socket */
  1936.             up->rdysock = s;
  1937.         }
  1938.         /* Load the addresses. Memory for the name has already
  1939.          * been allocated, either above or in the original bind.
  1940.          */
  1941.         sp.p = up->name;
  1942.         sp.nr->nr_family = AF_NETROM;
  1943.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->local);
  1944.         up->namelen = sizeof(struct sockaddr_nr);
  1945.  
  1946.         sp.p = up->peername;
  1947.         sp.nr->nr_family = AF_NETROM;
  1948.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->remote);
  1949.         up->peernamelen = sizeof(struct sockaddr_nr);
  1950.  
  1951.         /* Wake up the guy accepting it, and let him run */
  1952.         psignal(oup,1);
  1953.         pwait(NULL);
  1954.     }
  1955.      /* Ignore all other state transitions */    
  1956.     psignal(up,0);    /* In case anybody's waiting */
  1957. }
  1958. #endif
  1959.  
  1960. /* Verify address family and length according to the socket type */
  1961. static int
  1962. checkaddr(type,name,namelen)
  1963. int type;
  1964. char *name;
  1965. int namelen;
  1966. {
  1967.     union sp sp;
  1968.  
  1969.     sp.p = name;
  1970.     /* Verify length and address family according to protocol */
  1971.     switch(type){
  1972.     case TYPE_TCP:
  1973.     case TYPE_UDP:
  1974.         if(sp.in->sin_family != AF_INET
  1975.          || namelen != sizeof(struct sockaddr_in))
  1976.             return -1;
  1977.         break;
  1978. #ifdef    AX25
  1979.     case TYPE_AX25I:
  1980. #ifdef notdef
  1981.     case TYPE_AX25UI:
  1982. #endif
  1983.         if(sp.ax->sax_family != AF_AX25
  1984.          || namelen != sizeof(struct sockaddr_ax))
  1985.             return -1;
  1986.         break;
  1987. #endif
  1988. #ifdef    NETROM
  1989.     case TYPE_NETROML3:
  1990.     case TYPE_NETROML4:
  1991.         if(sp.nr->nr_family != AF_NETROM
  1992.          || namelen != sizeof(struct sockaddr_nr))
  1993.             return -1;
  1994.         break;
  1995. #endif
  1996.     }
  1997.     return 0;
  1998. }
  1999. /* Issue an automatic bind of a local address */
  2000. static void
  2001. autobind(s,af)
  2002. int s,af;
  2003. {
  2004.     char buf[MAXSOCKSIZE];
  2005.     union sp sp;
  2006.  
  2007.     sp.p = buf;
  2008.     switch(af){
  2009.     case AF_INET:
  2010.         sp.in->sin_family = AF_INET;
  2011.         sp.in->sin_addr.s_addr = INADDR_ANY;
  2012.         sp.in->sin_port = Lport++;
  2013.         bind(s,sp.p,sizeof(struct sockaddr_in));
  2014.         break;
  2015. #ifdef    AX25
  2016.     case AF_AX25:
  2017.         sp.ax->sax_family = AF_AX25;
  2018.         memset(sp.ax->ax25_addr,'\0',AXALEN);
  2019.         memset(sp.ax->iface,'\0',ILEN);
  2020.         bind(s,sp.p,sizeof(struct sockaddr_ax));
  2021.         break;
  2022. #endif
  2023. #ifdef    NETROM
  2024.     case AF_NETROM:
  2025.         sp.nr->nr_family = AF_NETROM;
  2026.         memcpy(sp.nr->nr_addr.user,Mycall,AXALEN);
  2027.         memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  2028.         bind(s,sp.p,sizeof(struct sockaddr_nr));
  2029.         break;
  2030. #endif
  2031.     }
  2032. }
  2033.  
  2034. /* this is called by tipmail only ! - WG7J */
  2035. #ifdef TIPMAIL
  2036.  
  2037. /* Return a pair of mutually connected sockets in sv[0] and sv[1] */
  2038. int
  2039. socketpair(af,type,protocol,sv)
  2040. int af;
  2041. int type;
  2042. int protocol;
  2043. int sv[];
  2044. {
  2045.     struct usock *up0, *up1;
  2046.     if(sv == NULLINT){
  2047.         errno = EFAULT;
  2048.         return -1;
  2049.     }
  2050.     if(af != AF_LOCAL){
  2051.         errno = EAFNOSUPPORT;
  2052.         return -1;
  2053.     }
  2054.     if(type != SOCK_STREAM && type != SOCK_DGRAM){
  2055.         errno = ESOCKTNOSUPPORT;
  2056.         return -1;
  2057.     }
  2058.     if((sv[0] = socket(af,type,protocol)) == -1)
  2059.         return -1;
  2060.     if((sv[1] = socket(af,type,protocol)) == -1){
  2061.         close_s(sv[0]);
  2062.         return -1;
  2063.     }
  2064.     up0 = itop(sv[0]);
  2065.     up1 = itop(sv[1]);
  2066.     up0->cb.local->peer = up1;
  2067.     up1->cb.local->peer = up0;
  2068.     return sv[1];
  2069. }
  2070. #endif
  2071.  
  2072.